﻿/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Secure Notepad Application
 * Version 2.00
 * 
 * Document Manager Class
 *      Provides a class for managing a text document, either secured or clear-text.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using Adaptive.Foundation;
using Adaptive.Foundation.Security;

namespace Adaptive.Foundation.IO
{
    /// <summary>
    /// Provides a class for managing a text document, either secured or clear-text.
    /// </summary>
    public sealed class TextDocumentManager : DisposableObjectBase, IDocument
    {
        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Password assigned to document.
        /// </summary>
        private UserPassword _documentPassword;
        /// <summary>
        /// Document instance.
        /// </summary>
        private IDocument _document;
        /// <summary>
        /// Type of document.
        /// </summary>
        private TextDocumentType _type = TextDocumentType.ClearText;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public TextDocumentManager()
            : base()
        {
            _type = TextDocumentType.ClearText;
            CreateDocumentInstance();
        }
        /// <summary>
        /// Initializes a new instance of the class to a clear-text file.
        /// </summary>
        /// <param name="fileName">
        /// The name of the file being created or opened.
        /// </param>
        public TextDocumentManager(string fileName)
            : base()
        {
            _type = TextDocumentType.ClearText;
            _document.FileName = fileName;
        }
        /// <summary>
        /// Initializes a new instance of the class to a secure text file.
        /// </summary>
        /// <param name="fileName">
        /// The name of the file being created or opened.
        /// </param>
        /// <param name="password">
        /// The document password.
        /// </param>
        public TextDocumentManager(string fileName, string password)
            : base()
        {
            _documentPassword = new UserPassword();
            _documentPassword.Value = password;
            _type = TextDocumentType.SecureText;
            CreateDocumentInstance();
            _document.FileName = fileName;
        }
        /// <summary>
        /// Initializes a new instance of the class to the specified document type.
        /// </summary>
        /// <param name="fileName">
        /// The name of the file being created or opened.
        /// </param>
        /// <param name="type">
        /// A <see cref="TextDocumentType"/> enumerated value indicating the
        /// type of document to be opened.
        /// </param>
        public TextDocumentManager(string fileName, TextDocumentType type)
            : base()
        {
            _type = type;
            CreateDocumentInstance();
            _document.FileName = fileName;
        }
        /// <summary>
        /// Initializes a new instance of the class to the specified document type.
        /// </summary>
        /// <param name="fileName">
        /// The name of the file being created or opened.
        /// </param>
        /// <param name="type">
        /// A <see cref="TextDocumentType"/> enumerated value indicating the
        /// type of document to be opened.
        /// </param>
        /// <param name="password">
        /// The document password to use.
        /// </param>
        public TextDocumentManager(string fileName, TextDocumentType type, string password)
            : base()
        {
            _type = type;
            CreateDocumentInstance();
            _document.FileName = fileName;

            _documentPassword = new UserPassword();
            _documentPassword.Value = password;
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if ((!Disposed) && (disposing))
            {
                if (_documentPassword != null)
                    _documentPassword.Dispose();

                if (_document != null)
                    ((IDisposable)_document).Dispose();
            }

            _document = null;
            _documentPassword = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets the type of document being managed,
        /// </summary>
        /// <value>
        /// A <see cref="TextDocumentType"/> enumerated value indicating the 
        /// type of underlying document.
        /// </value>
        public TextDocumentType DocumentType
        {
            get { return _type; }
        }
        /// <summary>
        /// Gets a value indicating whether the file has been loaded for editing.
        /// </summary>
        /// <value>
        /// <b>true</b> if the document is considered to be open; otherwise, <b>false</b>.
        /// </value>
        public bool IsOpen
        {
            get { return _document != null; }
        }
        /// <summary>
        /// Gets or sets the name of the file in which the data will be stored.
        /// </summary>
        /// <value>
        /// A fully-qualified path and file name.
        /// </value>
        public string FileName
        {
            get
            {
                string returnValue = string.Empty;          //Return value.

                if (_document != null)
                    returnValue = _document.FileName;

                return returnValue;
            }
            set
            {
                if (_document != null)
                    _document.FileName = value;
            }
        }
        /// <summary>
        /// Gets or sets the contents of the file.
        /// </summary>
        /// <value>
        /// The text contents read from disk and/or to be written to disk.
        /// </value>
        public string Text
        {
            get
            {
                string returnValue = string.Empty;

                if (_document != null)
                    returnValue = _document.Text;

                return returnValue;
            }
            set
            {
                if (_document != null)
                    _document.Text = value;
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Public Methods / Functions
        /// <summary>
        /// Loads the content of the document into memory.
        /// </summary>
        /// <returns>
        /// <b>true</b> if the operation is successful; otherwise, <b>false</b>.
        /// </returns>
        public bool Load()
        {
            //Set the password if the file is a secure type.
            if (_document is SecureTextDocument)
                ((SecureTextDocument)_document).SetPassword(_documentPassword.Value);

            return _document.Load();
        }
        /// <summary>
        /// Saves the content of the document to disk.
        /// </summary>
        /// <returns>
        /// <b>true</b> if the operation is successful; otherwise, <b>false</b>.
        /// </returns>
        public bool Save()
        {
            //Set the password if the file is a secure type.
            if (_document is SecureTextDocument)
                ((SecureTextDocument)_document).SetPassword(_documentPassword.Value);

            return _document.Save();
        }
        /// <summary>
        /// Sets the content of the document password to be used when loading 
        /// a secure document.
        /// </summary>
        /// <param name="userPassword">
        /// The password value supplied by the user.
        /// </param>
        public void SetDocumentPassword(string userPassword)
        {
            SecureTextDocument newDocument = null;

            if (_documentPassword != null)
            {
                _documentPassword.Dispose();
            }
            _documentPassword = new UserPassword();
            _documentPassword.Value = userPassword;
            userPassword = null;

            if (_document is ClearTextDocument)
            {
                //Translate the document type.
                newDocument = new SecureTextDocument();
                newDocument.FileName = _document.FileName;
                newDocument.SetPassword(userPassword);
                newDocument.Text = _document.Text;

                ((IDisposable)_document).Dispose();
                _document = null;
                _document = newDocument;
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Event Handlers
         *------------------------------------------------------------------------------*/
        #region Private Event Handlers
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Methods / Functions
         *------------------------------------------------------------------------------*/
        #region Private Methods / Functions
        /// <summary>
        /// Creates an <b>IDocument</b> instance based on the file extension of the supplied
        /// name.
        /// </summary>
        private void CreateDocumentInstance()
        {
            switch (_type)
            {
                case TextDocumentType.ClearText:
                    _document = new ClearTextDocument();
                    break;

                case TextDocumentType.SecureText:
                    _document = new SecureTextDocument();
                    break;
            }
        }
        #endregion
    }
}
